package com.bestcem.xm.user.service.impl.third;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.user.config.properties.SettingProperties;
import com.bestcem.xm.user.service.dto.third.ConversionType;
import com.bestcem.xm.user.service.third.BaiduOcpcService;
import com.bestcem.xm.user.util.business.UrlUtils;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 百度营销服务类
 * API文档地址: https://dev2.baidu.com/content?sceneType=0&pageId=101211&nodeId=658&subhead=2.4%20%E8%81%94%E8%B0%83
 *
 * @author wangyunyun <yunyun.wang@idiaoyan.com>
 * @version v1.0
 * @date 2022/3/1 14:30
 */
@Slf4j
@Service
public class BaiduOcpcServiceImpl implements BaiduOcpcService {

    @Autowired
    private SettingProperties settingProperties;

    /**
     * 默认转化类型
     */
    private static final Integer DEFAULT_NEW_TYPE = 27;

    /**
     * 请求成功编码
     */
    private static final int BAIDU_OCPC_SUCCESS_CODE = 0;

    /**
     * 百度流量标识参数
     */
    private static final String BAIDU_OCPC_BD_VID = "bd_vid";

    @Override
    @Async
    public void sendConvertData(Integer newType, String logidUrl) {
        // 校验参数: 落地页Url不存在或者落地页Url上的百度流量标识参数为空, 则直接返回
        if (StringUtils.isBlank(logidUrl) || StringUtils.isBlank(UrlUtils.getParam(logidUrl, BAIDU_OCPC_BD_VID))) {
            return;
        }

        // 设置转化数据参数
        List<ConversionType> conversionTypeList = new ArrayList<>();
        ConversionType cv = new ConversionType();
        cv.setLogidUrl(logidUrl);
        cv.setNewType(newType != null ? newType : DEFAULT_NEW_TYPE);
        conversionTypeList.add(cv);

        // 设置请求参数
        JsonObject data = new JsonObject();
        // 设置API接口回传Token
        data.addProperty("token", settingProperties.getBaiduOcpcToken());
        // 设置API接口回传conversionTypes
        data.add("conversionTypes",
                new Gson().toJsonTree(conversionTypeList, new TypeToken<List<ConversionType>>() {
                }.getType()).getAsJsonArray());

        // 向百度发送数据
        sendWithData(data.toString());
    }

    /**
     * 发送数据回传请求
     *
     * @param data 回传数据对象
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/3/4 11:50
     */
    private void sendWithData(String data) {
        // 基线环境直接返回
        if (settingProperties.isBaseLine()) {
            return;
        }

        if (StringUtils.isBlank(settingProperties.getBaiduOcpcUploadConvertDataUrl())) {
            log.error("[User] 调用百度营销服务失败：服务地址不能为空");
            return;
        }

        // 发送请求
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(settingProperties.getBaiduOcpcUploadConvertDataUrl());
        post.setHeader("Content-type", "application/json; charset=UTF-8");
        StringEntity entity = new StringEntity(data, StandardCharsets.UTF_8);
        entity.setContentEncoding("UTF-8");
        post.setEntity(entity);

        try {
            HttpResponse response = client.execute(post);
            // 检验状态码，如果成功接收数据
            int code = response.getStatusLine().getStatusCode();
            if (code == HttpStatus.SC_OK) {
                String res = EntityUtils.toString(response.getEntity());
                JSONObject returnData = JSON.parseObject(res);
                int status = returnData.getJSONObject("header").getIntValue("status");
                // 判断是否请求成功, 请求失败打印出错信息
                if (BAIDU_OCPC_SUCCESS_CODE != status) {
                    log.error("baidu ocpc req error. res data: {}", res);
                }
            }
        } catch (IOException e) {
            log.error("baidu ocpc req error", e);
            log.error("baidu ocpc req error. data: {}", data);
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                log.error("baidu ocpc client close error: ", e);
            }
        }
    }

}
